package org.apache.nutch.indexer.mongodb;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.mongodb.BasicDBList;
import com.mongodb.DB;
import com.mongodb.Mongo;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;

public class ImageDownloader {

	// public Logger LOG = Logger.getLogger(ImageDownloader.class);

	public static List<String> IMAGETYPE = Arrays
			.asList(MongodbConstants.IMAGE_TYPE.split("|"));

	GridFS gridFS;

	public ImageDownloader(DB mongodb) {
		gridFS = new GridFS(mongodb);
		// LOG.info("init GridFS ok!");
	}

	/**
	 * 
	 * @param htmlURL
	 * @param save
	 *            是否保存图片到mongodb中，true为保存
	 * @return
	 */
	public BasicDBList saveImages(String htmlURL, boolean save) {
		try {
			BasicDBList images = new BasicDBList();
			Document doc = Jsoup.connect(htmlURL).get();
			Elements imageElements = doc.getElementsByTag("img");
			List<String> urls = new ArrayList<String>();
			for (Element image : imageElements) {

				// TODO 有些网站不是src字段，比如美空首页是src2，需要针对不同的URL建立模板爬取
				String imageSrc = image.absUrl("src");
				// URL校验，必须为完整的URL地址，带http
				if (imageURLVerify(imageSrc)) {
					urls.add(imageSrc);
				}
			}
			// LOG.info("page " + htmlURL + " contains image count:" +
			// urls.size());
			if (!save) {
				images.addAll(urls);
				return images;
			}
			images = download(urls);
			// LOG.debug("this page save image count:" + images.size());
			return images;
		} catch (Exception e) {
			// LOG.error("connect to :" + htmlURL + " error");
			e.printStackTrace();
		}
		return null;
	}

	private BasicDBList download(List<String> urls)
			throws MalformedURLException, IOException {
		BasicDBList bdbList = new BasicDBList();

		for (int i = 0; i < urls.size(); i++) {
			GridFSInputFile img = saveInGridFS(gridFS, urls.get(i));
			if (img != null) {
				bdbList.add(img);
			}
		}
		// LOG.info("BasicDBList size:" + bdbList.size());
		return bdbList;
	}

	private GridFSInputFile saveInGridFS(GridFS myFS, String url) {
		InputStream in = null;
		URL _url;
		URLConnection conn;
		StringBuilder imgName = new StringBuilder();
		try {
			_url = new URL(url);
			conn = _url.openConnection();

			conn.setConnectTimeout(2000);
			conn.setReadTimeout(2000);
			in = conn.getInputStream();

			BufferedInputStream bis = new BufferedInputStream(in);

			// TODO 5MB大小的文件，大于会报错，需要写入配置文件
			bis.mark(1024 * 1024 * 1024 * 5);

			BufferedImage bi = ImageIO.read(bis);
			int width = bi.getWidth();
			int height = bi.getHeight();

			imgName.append(String.valueOf(System.currentTimeMillis()));
			imgName.append("_").append(width);
			imgName.append("_").append(height);

			if (!getImageName(url, imgName)) {
				// LOG.error("image name is error , check url :" + url);
				return null;
			}
			bis.reset();
			GridFSInputFile image = myFS.createFile(bis, imgName.toString(),
					true);
			long startTime = System.currentTimeMillis();
			for (int k = 0; k < 1000000; k++) {
				// image.setFilename(imgName.toString());
				image.setFilename("img_" + k);
				image.save();
			}
			System.out.println(System.currentTimeMillis() - startTime);

			// LOG.info("saving image in gridFS named: " + imgName.toString());
			bis.close();
			in.close();
			return image;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 对异常URL的处理
			// LOG.error("maybe connection timeout! image url:" + url);
		}
		return null;
	}

	public boolean getImageName(String imageURL, StringBuilder sb) {
		String patternStr = "\\w*.(jpg|bmp|gif|jpeg|tif|png)";
		Pattern pattern = Pattern.compile(patternStr);
		Matcher matcher = pattern.matcher(imageURL);
		if (matcher.find()) {
			sb.append(".").append(matcher.group());
			return true;
		}
		return false;
	}

	/**
	 * 
	 * @param imageURL
	 * @return
	 */
	public boolean imageURLVerify(String imageURL) {
		String patternStr = "(http|https)://[^\":<>]*\\.("
				+ MongodbConstants.IMAGE_TYPE + ")";
		Pattern pattern = Pattern.compile(patternStr);
		Matcher matcher = pattern.matcher(imageURL);
		return matcher.matches(); // 必须完全匹配
	}

	public static void main(String[] args) throws UnknownHostException {
		Mongo mongo = new Mongo();
		DB db = mongo.getDB("test");
		ImageDownloader id = new ImageDownloader(db);
		// http://qing.weibo.com/tag/%E7%BE%8E%E5%A5%B3
		// http://www.2345.com/zt/girl.htm
		id.saveImages("http://qing.weibo.com/tag/%E7%BE%8E%E5%A5%B3", true);
	}
}
